package com.neuronbit.businessflow.intellij.editor.swing.editor.propertyInspector.properties;

import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.util.Computable;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiParameter;
import com.intellij.refactoring.changeSignature.JavaChangeSignatureDialog;
import com.intellij.refactoring.changeSignature.ParameterInfoImpl;
import com.intellij.ui.JBColor;
import com.neuronbit.businessflow.intellij.editor.UIDesignerBundle;
import com.neuronbit.businessflow.intellij.editor.swing.editor.FormEditingUtil;
import com.neuronbit.businessflow.intellij.editor.swing.editor.RadComponent;
import com.neuronbit.businessflow.intellij.editor.swing.editor.RadJavaMethodComponent;
import com.neuronbit.businessflow.intellij.editor.swing.editor.propertyInspector.InplaceContext;
import com.neuronbit.businessflow.intellij.editor.swing.editor.propertyInspector.Property;
import com.neuronbit.businessflow.intellij.editor.swing.editor.propertyInspector.PropertyEditor;
import com.neuronbit.businessflow.intellij.model.FormattedMethodString;
import com.neuronbit.businessflow.intellij.util.PsiUtils;
import org.apache.commons.lang3.ArrayUtils;

import javax.swing.*;
import java.util.List;

/**
 * The type Change method signature property editor.
 */
public class ChangeMethodSignaturePropertyEditor extends PropertyEditor {
    private final TextFieldWithBrowseButton myTf = new TextFieldWithBrowseButton();
    private final RadJavaMethodComponent component;

    /**
     * Instantiates a new Change method signature property editor.
     *
     * @param component the component
     */
    ChangeMethodSignaturePropertyEditor(RadJavaMethodComponent component) {
        this.component = component;
        myTf.setText(UIDesignerBundle.message("client.properties.configure"));
        myTf.getTextField().setEditable(false);
        myTf.getTextField().setBorder(null);
        myTf.getTextField().setForeground(JBColor.foreground());
        myTf.addActionListener(e -> showClientPropertiesDialog());
    }

    private void showClientPropertiesDialog() {
//            ConfigureClientPropertiesDialog dlg = new ConfigureClientPropertiesDialog(myProject);
//            dlg.show();
//            if (dlg.getExitCode() == DialogWrapper.OK_EXIT_CODE) {
//                dlg.save();
//                fireValueCommitted(true, false);
//            }
        ApplicationManager.getApplication().runReadAction((Computable<Property[]>) () -> {
            if (component.getClassToBind() == null) {
                return Property.EMPTY_ARRAY;
            }
            PsiClass clazz = FormEditingUtil.findClassToBind(component.getModule(), component.getClassToBind());
            if (clazz == null) {
                return Property.EMPTY_ARRAY;
            }
            FormattedMethodString methodToBind = component.getMethodToBind();
            if (null != methodToBind) {
                String methodName = methodToBind.getName();
                PsiMethod[] psiMethods = clazz.findMethodsByName(methodName, true);
                if (ArrayUtils.isNotEmpty(psiMethods)) {
                    for (PsiMethod psiMethod : psiMethods) {
                        if (PsiUtils.formatMethod(psiMethod).equals(methodToBind.getValue())) {
                            PsiParameter[] parameters = psiMethod.getParameterList().getParameters();
                            ParameterInfoImpl[] parameterInfos = new ParameterInfoImpl[parameters.length];
                            for (int i = 0; i < parameters.length; i++) {
                                parameterInfos[i] = ParameterInfoImpl.create(i).withName(parameters[i].getName()).withType(parameters[i].getType());
                            }
                            final JavaChangeSignatureDialog dialog = JavaChangeSignatureDialog.createAndPreselectNew(
                                    component.getProject(), psiMethod,
                                    List.of(parameterInfos),
                                    false,
                                    null);
                            dialog.show();
                            //通过 refactor 的能力，如果正确的加上了 usage，那么在 refactor 的时候，以及 undo 的时候，应该是可以正确的变更文件内容的
                            //component.setMethodToBind(PsiUtils.formatMethod(psiMethod));
                            break;
                        }
                    }

                }
            }
            return Property.EMPTY_ARRAY;
        });

    }

    @Override
    public Object getValue() throws Exception {
        return null;
    }

    @Override
    public JComponent getComponent(final RadComponent component, final Object value, final InplaceContext inplaceContext) {
        return myTf;
    }

    @Override
    public void updateUI() {
        SwingUtilities.updateComponentTreeUI(myTf);
    }
}
